package zhoug.zui;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import zhoug.common.interfaces.TextChangedListener;
import zhoug.common.utils.AttributeUtils;
import zhoug.common.utils.MathUtils;
import zhoug.common.view.edit.ZEditText;
import zhoug.common.view.edit.ZTextWatcher;
import zhoug.logging.Logger;

/**
 * 步进器
 *
 * @Author: zhoug
 * @Date: 2024-07-15
 * @Description:
 */
public class ZUINumberStepView extends FrameLayout {
    private static final String TAG = ">>>ZUINumberStepView";
    private static final int[] STATE_ERROR = {
            R.attr.zui_state_error
    };
    private static final int[] STATE_FOCUSED = {
            android.R.attr.state_focused
    };
    protected ImageView mLeftImageView;
    protected ImageView mRightImageView;
    protected ZEditText mEditText;
    /**
     * 是否可以输入,false:只能点击按钮输入,true:可以键盘输入
     */
    protected boolean mEditEnabled = true;
    /**
     * 标记错误提示
     */
    protected boolean mIsError;
    /**
     * 允许输入最大值
     */
    protected double maxNumber = Double.MAX_VALUE;
    /**
     * 允许输入的最小值
     */
    protected double minNumber = 0;
    /**
     * 当前输入的值
     */
    protected double mValue;
    /**
     * 每次加减的步长
     */
    protected double step = 1;//步长
    /**
     * 小数位数
     */
    protected int decimal = 2;

    /**
     * 数据改变监听器
     */
    protected OnNumberChangeListener onNumberChangeListener;
    /**
     * 标记改变数据时是否回调{@link OnNumberChangeListener}
     */
    protected boolean invokeListener = true;
    /**
     * 失去焦点的时候验证数据的合法性
     */
    protected boolean mValidateOutFocus = false;
    /**
     * 循环:点击按钮小于最小值后又从最大值开始,大于最大值后又从最小值开始
     */
    protected boolean mLoop = true;

    public ZUINumberStepView(@NonNull Context context) {
        this(context, null);
    }

    public ZUINumberStepView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.ZUINumberStepView_theme);
    }

    public ZUINumberStepView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);

    }

    private void init(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        View root = LayoutInflater.from(context).inflate(R.layout.zui_number_step_view, this, false);
        addView(root);
        mLeftImageView = root.findViewById(R.id.step_iv_left);
        mRightImageView = root.findViewById(R.id.step_iv_right);
        mEditText = root.findViewById(R.id.step_editText);


        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ZUINumberStepView, defStyleAttr, R.style.ZUINumberStepView_def);
        int valueHeight = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_valueHeight, ViewGroup.LayoutParams.WRAP_CONTENT);
        int iconWidth = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconWidth, 0);
        int iconHeight = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconHeight, 0);
        int iconPaddingStart = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconPaddingStart, 0);
        int iconPaddingEnd = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconPaddingEnd, 0);
        int iconPaddingTop = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconPaddingTop, 0);
        int iconPaddingBottom = a.getDimensionPixelOffset(R.styleable.ZUINumberStepView_zui_iconPaddingBottom, 0);
        Drawable leftIcon = a.getDrawable(R.styleable.ZUINumberStepView_zui_leftIcon);
        Drawable rightIcon = a.getDrawable(R.styleable.ZUINumberStepView_zui_rightIcon);
        Drawable leftIconBackground = a.getDrawable(R.styleable.ZUINumberStepView_zui_leftIconBackground);
        Drawable rightIconBackground = a.getDrawable(R.styleable.ZUINumberStepView_zui_rightIconBackground);
        ColorStateList iconTint = a.getColorStateList(R.styleable.ZUINumberStepView_zui_iconTint);
        String valueHint = a.getString(R.styleable.ZUINumberStepView_zui_valueHint);
        int valueHintColor = a.getColor(R.styleable.ZUINumberStepView_zui_valueHintColor, 0);
        int valueColor = a.getColor(R.styleable.ZUINumberStepView_zui_valueColor, 0);
        float valueSize = a.getDimension(R.styleable.ZUINumberStepView_zui_valueSize, 0);
        int valueStyle = a.getInt(R.styleable.ZUINumberStepView_zui_valueStyle, Typeface.NORMAL);
        int valueGravity = a.getInt(R.styleable.ZUINumberStepView_zui_valueGravity, Gravity.CENTER);
        Drawable valueBackground = a.getDrawable(R.styleable.ZUINumberStepView_zui_valueBackground);
        boolean editEnabled = a.getBoolean(R.styleable.ZUINumberStepView_zui_editEnabled, true);
        Drawable textCursorDrawable=a.getDrawable(R.styleable.ZUINumberStepView_android_textCursorDrawable);

        a.recycle();
        zhoug.common.utils.TextUtils.setTextCursorDrawable(mEditText, textCursorDrawable);

        setEditEnabled(editEnabled);
        //按钮图标
        if (leftIcon != null) {
            mLeftImageView.setImageDrawable(leftIcon);
        }
        if (rightIcon != null) {
            mRightImageView.setImageDrawable(rightIcon);
        }
        AttributeUtils.setImageTintList(mLeftImageView, iconTint);
        AttributeUtils.setImageTintList(mRightImageView, iconTint);
        //设置按钮大小
        AttributeUtils.setSizeExcludeZero(mLeftImageView, iconWidth, iconHeight);
        AttributeUtils.setSizeExcludeZero(mRightImageView, iconWidth, iconHeight);
        //设置按钮背景
        mLeftImageView.setBackground(leftIconBackground);
        mRightImageView.setBackground(rightIconBackground);
        //设置按钮padding
        mLeftImageView.setPadding(iconPaddingStart, iconPaddingTop, iconPaddingEnd, iconPaddingBottom);
        mRightImageView.setPadding(iconPaddingStart, iconPaddingTop, iconPaddingEnd, iconPaddingBottom);
        //设置文本属性
        mEditText.setHint(valueHint);
        if (valueHintColor != 0) {
            mEditText.setHintTextColor(valueHintColor);
        }
        if (valueColor != 0) {
            mEditText.setTextColor(valueColor);
        }
        AttributeUtils.setTextSize(mEditText, valueSize, 0);
        AttributeUtils.setTypeface(mEditText, valueStyle);
        mEditText.setGravity(valueGravity);
        mEditText.setBackground(valueBackground);
        AttributeUtils.setSizeExcludeZero(mEditText, 0, valueHeight);
        //改变背景色状态
        mEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                refreshDrawableState();
                if (!hasFocus) {
                    boolean validate = validate();
                    //失去焦点
                    if (mValidateOutFocus) {
                        setIsError(!validate);
                    } else if (validate) {
                        setIsError(false);
                    }
                }

            }
        });
        mLeftImageView.setOnClickListener(v -> {
            if (!mEditText.hasFocus()) {
                mEditText.requestFocus();
            }
            changeNumber(false);
        });

        mRightImageView.setOnClickListener(v -> {
            if (!mEditText.hasFocus()) {
                mEditText.requestFocus();
            }
            changeNumber(true);
        });
        mEditText.addTextChangedListener(new TextChangedListener() {
            @Override
            public void afterTextChanged(Editable s) {
                if (!invokeListener) {
                    return;
                }
                double val = 0;
                if (s != null) {
                    try {
                        String trim = s.toString().trim();
                        if (!trim.isEmpty()) {
                            val = Double.parseDouble(trim);
                        }
                        //限制输入的最大值最小值
                        //注最小值不好限制,比如限制最小值为5,当想输入23的时候,输入2会被拦截到
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
                mValue = val;
                if (onNumberChangeListener != null) {
                    onNumberChangeListener.onNumberChange(ZUINumberStepView.this, mValue);
                }
            }
        });


    }


    /**
     * 改变数据
     *
     * @param add true:增加,false:减少
     */
    protected void changeNumber(boolean add) {
        if (!isEnabled()) return;
        double val = mValue;
        if (add) {
            val += step;
            if (!validate(val)) {
                if (mLoop) {
                    val = minNumber;
                } else {
                    val = maxNumber;
                }
            }
        } else {
            val -= step;
            if (!validate(val)) {
                if (mLoop) {
                    val = maxNumber;
                } else {
                    val = minNumber;
                }
            }
        }
        if(val!=mValue){
            setNumber(val);
        }
    }

    /**
     * 设置数据 默认回调{@link OnNumberChangeListener},如果设置了话
     *
     * @param value 数据
     */
    public void setNumber(double value) {
        setNumber(value, true);
    }

    /**
     * 设置数据
     *
     * @param value          数据
     * @param invokeListener 是否回调{@link OnNumberChangeListener},如果设置了话
     */
    public void setNumber(double value, boolean invokeListener) {
        this.mValue = value;
        if (!invokeListener) {
            this.invokeListener = false;
            setText(MathUtils.formatDecimalUp(mValue, decimal, false));
            this.invokeListener = true;
        } else {
            setText(MathUtils.formatDecimalUp(mValue, decimal, false));
        }
    }

    private void setText(String s) {
        mEditText.setText(s);
        if (s != null && !s.isEmpty()) {
            mEditText.setSelection(s.length());
        }

    }

    /**
     * 设置小数位数
     *
     * @param decimal
     */
    public void setDecimal(int decimal) {
        this.decimal = decimal;
    }


    /**
     * 设置最小值和最大值
     *
     * @param minNumber 最小值 默认0
     * @param maxNumber 最大值 默认{@link Double#MAX_VALUE}
     */
    public void setMinMaxNumber(double minNumber, double maxNumber) {
        this.minNumber = minNumber;
        this.maxNumber = maxNumber;
        int inputType = mEditText.getInputType();
        if (minNumber < 0) {
            inputType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
        } else {
            inputType &= ~InputType.TYPE_NUMBER_FLAG_SIGNED;
        }
        setInputType(inputType);
    }

    /**
     * @param inputType {@link  InputType#TYPE_CLASS_NUMBER} ...
     */
    public void setInputType(int inputType) {
        mEditText.setInputType(inputType);
    }

    /**
     * @param decimal
     */
    public void setIsDecimal(boolean decimal) {
        int inputType = mEditText.getInputType();
        if (decimal) {
            //小数
            inputType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
        } else {
            inputType &= ~InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }
        setInputType(inputType);
    }

    public void setLoopMinMax(boolean loop) {
        this.mLoop = loop;
    }

    /**
     * 每次加减的步长
     *
     * @param step 默认1
     */
    public void setStep(double step) {
        this.step = step;
    }

    /**
     * 验证数据是否合法
     *
     * @param value
     * @return
     */
    protected boolean validate(double value) {
        return value >= minNumber && value <= maxNumber;
    }


    /**
     * 验证数据是否合法
     *
     * @return
     */
    public boolean validate() {
        return validate(mValue);
    }

    /**
     * 验证数据是否合法,不合法时自定设置{@link #setIsError(boolean)}
     *
     * @return
     */
    public boolean validateAndShowError() {
        boolean validate = validate(mValue);
        setIsError(!validate);
        return validate;
    }

    public void setValidateOutFocus(boolean validateOutFocus) {
        this.mValidateOutFocus = validateOutFocus;
    }

    public void addTextChangedListener(TextWatcher watcher) {
        mEditText.addTextChangedListener(watcher);
    }

    public void addTextChangedListener(ZTextWatcher watcher) {
        mEditText.addTextChangedListener(watcher);
    }

    public void removeTextChangedListener(TextWatcher watcher) {
        mEditText.removeTextChangedListener(watcher);
    }

    public void removeTextChangedListener(ZTextWatcher watcher) {
        mEditText.removeTextChangedListener(watcher);
    }


    public ZEditText getEditText() {
        return mEditText;
    }

    public ImageView getLeftImageView() {
        return mLeftImageView;
    }

    public ImageView getRightImageView() {
        return mRightImageView;
    }


    /**
     * 设置数据改变回调
     *
     * @param onNumberChangeListener
     */
    public void setOnNumberChangeListener(OnNumberChangeListener onNumberChangeListener) {
        this.onNumberChangeListener = onNumberChangeListener;
    }

    public interface OnNumberChangeListener {
        void onNumberChange(ZUINumberStepView numberStepView, double number);
    }

    /**
     * 设置错误提示
     *
     * @param isError
     */
    public void setIsError(boolean isError) {
        if (mIsError != isError) {
            this.mIsError = isError;
            refreshDrawableState();
        }
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        refreshEditEnabled();
        mLeftImageView.setEnabled(enabled);
        mRightImageView.setEnabled(enabled);

    }

    /**
     * 是否可以输入
     *
     * @param editEnabled false:只能点击按钮输入,true:可以键盘输入
     */
    public void setEditEnabled(boolean editEnabled) {
        if (this.mEditEnabled != editEnabled) {
            this.mEditEnabled = editEnabled;
            refreshEditEnabled();
        }
    }

    protected void refreshEditEnabled() {
        mEditText.setEnabled(mEditEnabled && isEnabled());
    }


    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mIsError) {
            int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            mergeDrawableStates(drawableState, STATE_ERROR);
            return drawableState;
        } else if (mEditText != null && mEditText.hasFocus()) {
            Logger.d(TAG, "hasFocus:" + hasFocus());
            Logger.d(TAG, "mEditText.hasFocus:" + mEditText.hasFocus());
            int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            mergeDrawableStates(drawableState, STATE_FOCUSED);
            return drawableState;
        } else {
            return super.onCreateDrawableState(extraSpace);
        }
    }

}
